FAQ & Troubleshooting
Common Questions
How do I add a new mock API endpoint?
- Web
- Mobile
Add an entry to node_modules/@cdx-extensions/di-sdk-web/dist/mocks/apiResponses.json with url, method, status, data, and optionally delay. It will be registered on the next widget start.
Add an entry to the responses array in node_modules/@cdx-extensions/di-sdk-mobile/dist/mocks/apiResponses.json with url, method, status, data, and optionally delay. The url must be the full URL that your code builds from config.baseUrl + config.apiPath — the mock adapter matches by exact URL string. It will be registered on the next widget start.
I want to call a real API locally. How?
- Web
- Mobile
Set isMock = false in node_modules/@cdx-extensions/di-sdk-web/dist/httpClient.js line 8, add your access_token on line 10, and set the real base URL in widgets/web/<widget>/src/environments/environment.ts. This is reset by npm install.
Set isMock = false (find the isMock variable near the top of node_modules/@cdx-extensions/di-sdk-mobile/dist/httpClient.js), set your token in the access_token variable in the same file, and update the base URL in your config.ts. These changes are reset by npm install.
useUserContext() returns the same data every time locally.
- Web
- Mobile
It reads from node_modules/@cdx-extensions/di-sdk-web/dist/mocks/userContext.json. Edit that file to change the mock user's role, institution, email, etc.
It reads from node_modules/@cdx-extensions/di-sdk-mobile/dist/mocks/userContext.json. Edit that file to change the mock user's role, institution, email, etc.
My API call returns mock data locally but fails in production.
- Web
- Mobile
A cdx-extensions package version mismatch may cause this issue. Verify the required versions in the shared dependencies table.
The domain you are calling is likely not whitelisted in the platform's network configuration, or there is a cdx-extensions package version mismatch. Contact the platform team with the exact API domain to request whitelisting. Verify the required peer and shared dependency versions in the README. See Host App Integration for packaging, build output, and registration with the platform team.
Platform-Specific Questions
- Web
- Mobile
The widget works locally but is blank on the platform homepage.
Check: name in module-federation.config.ts matches what the host expects; exposes path points to a component with a valid default export; the build output is deployed to the correct static content location.
What is the mobile banking host app and who manages it?
The mobile banking host application is the Candescent mobile app that loads and renders features and widgets in production. It is managed by the Candescent platform team. Features and widgets run inside this host app as embedded React Native packages — they are not standalone apps. Contact the Candescent technical support team to help integrate your developed features or widgets with the mobile banking host.
What is the difference between a feature and a widget?
A feature is a full-screen experience that appears as a new bottom tab in the mobile banking app. A widget is a component embedded in the existing home screen of the mobile banking app. Both use the same SDK (@cdx-extensions/di-sdk) and can leverage any SDK capability (useUserContext, useBranding, getHttpClient).
The sandbox fails to start with a Metro bundler error.
Make sure all packages are built first (npx nx run <name>:build). Metro resolves local workspace packages via symlinks, and the compiled dist/ output must exist.
If Metro cannot resolve your package, check metro.config.js in playground/mobile-sandbox/. The file uses config.resolver.extraNodeModules with a Proxy to map package names to workspace paths. If you used either generator (@cdx-extensions/widget-template-mobile:feature or :widget), it automatically registered your project in metro.config.js. If you created the project manually, add an explicit mapping for your package inside the Proxy's get handler:
if (name === '@acme-extensions/your-feature') {
return path.join(workspaceRoot, 'samples', 'mobile', 'feature', 'your-feature');
}
Also verify that tsconfig.json in the sandbox has a path mapping for your package under compilerOptions.paths.
How do I add my feature or widget to the sandbox navigation?
If you used the generator, your project is already registered in the sandbox. If you created it manually, refer to the existing sandbox screens for the pattern — create a screen in screens/ and register it in navigation/tabs.tsx.
How do I test with different institution brandings?
The sandbox includes a branding switcher. Tap the gear icon in the navigation header to select from five built-in theme variants (Classic Blue, Purple Elegance, Ocean Blue, Forest Green, Crimson Red). Your feature or widget receives the selected theme automatically through sdk.useBranding(). To add a custom branding for testing, create a new JSON file under node_modules/@cdx-extensions/di-sdk-mobile/dist/mocks/ following the MobileBrandingResponse shape and register it in BrandingProvider.tsx.
My Nx cache errors during a build.
Run with --skip-nx-cache if you experience stale cache issues:
npx nx run my-feature:build --skip-nx-cache
My feature or widget works in the sandbox but not in the production app.
Run through this debugging checklist:
- Package name matches: The npm package name (e.g.
@acme-extensions/my-feature) must exactly match what the platform team registered for the host app. - Version matches: The release version must match what the host app expects. Confirm this with the platform team.
- Exports are correct: Your
src/index.tsmust export the component with both a named export and a default export. Some host app configurations useimport Component from '...'. - Integration type matches: Confirm that the registered integration type (
widgetorfeature) matches what you built. A feature registered as a widget (or vice versa) may not render correctly. - Peer dependencies satisfied: All
peerDependenciesdeclared in yourpackage.jsonmust be provided by the host app at the correct versions. Mismatched React or React Native versions will cause runtime crashes. - API domain is whitelisted: If your feature or widget makes API calls, the target domain must be whitelisted in the platform's network configuration. Contact the platform team with the exact domain.
- Build output is complete: Verify the package the host consumes includes
dist/index.js,dist/index.mjs, anddist/index.d.ts.
Pre-Submission Checklist
Confirm each of the following before submitting your widget to the platform team.
- Web
- Mobile
| Check | How to Verify |
|---|---|
| Renders without errors | Run nx serve <widget> and open in browser |
| User context displays correctly | Verify the user name/email from userContext.json appears as expected |
| API calls return mock data | Trigger any data-fetching action and confirm the response matches apiResponses.json |
| Branding renders correctly | Switch between branding-1 through branding-5 and verify colors/fonts update |
| TypeScript compiles cleanly | Run nx build <widget> and confirm zero errors |
| Module Federation config is correct | Verify name and exposes in module-federation.config.ts match your component |
| Build output is correct | Run nx build <widget> --configuration=production and verify dist/ contains remoteEntry.js |
| Check | How to Verify |
|---|---|
| Renders without errors | Run npx nx start mobile-sandbox and navigate to your feature's tab or the Widgets screen |
| User context displays correctly | Verify the user name/email from userContext.json appears as expected |
| API calls return mock data | Trigger any data-fetching action and confirm the response matches apiResponses.json |
| Loading states work | Observe the loading indicator before mock data resolves (simulated delay) |
| Error handling works | Temporarily remove your endpoint from apiResponses.json and verify an error state displays gracefully |
| Branding renders correctly | Use the gear icon to switch between all branding variants and verify colors/fonts update |
| Different user scenarios | Edit userContext.json to test with different roles (PRIMARY, ADMIN), institution IDs, and user names |
| TypeScript compiles cleanly | Run npx nx run <name>:typecheck and confirm zero errors |
| Build output is correct | Run npx nx run <name>:build and verify the dist/ folder contains index.js, index.mjs, and index.d.ts |
Testing with Real APIs
To verify your widget against a real backend during development:
- Web
- Mobile
- Set
isMock = falseinnode_modules/@cdx-extensions/di-sdk-web/dist/httpClient.js(line 8). - Provide a valid token in the
access_tokenvariable (line 10). - Update your widget's environment file with the real API base URL (
widgets/web/<widget>/src/environments/environment.ts). - Start the widget with
nx serve <widget>and exercise all API-dependent flows. - Confirm that responses render correctly and error states are handled.
- Set
isMock = falseinnode_modules/@cdx-extensions/di-sdk-mobile/dist/httpClient.js(find theisMockvariable near the top of the file). - Provide a valid token in the
access_tokenvariable in the same file. - Update
config.tswith your real API base URL. - Start the sandbox and exercise all API-dependent flows.
- Confirm that responses render correctly and error states are handled.
Remember to revert httpClient.js changes before running npm install, or they will be overwritten.
Recommendations
- Web
- Mobile
| Do | Don't |
|---|---|
Use sdk.getHttpClient() for all API calls | Use raw fetch() or import Axios directly |
Import SDK from @cdx-extensions/di-sdk only | Import from @cdx-extensions/di-sdk-web in widget code |
Use config.ts or environment files for API endpoint configuration | Hardcode API URLs directly in component code |
Modify userContext.json to test different user scenarios locally | Change the structure of module-federation.config.ts or package.json |
Add mock endpoints to apiResponses.json for local testing | Remove existing entries from root package.json |
Keep peerDependencies aligned with those in the shared dependencies table | Change React, MUI, or SDK versions independently |
Copy the module-federation.config.ts pattern to your new widget | Assume the widget runs standalone — it always runs inside the OLB host |
Set isMock = false in httpClient.js only for local real-call testing | Commit node_modules/ changes |
| Contact the support team for domain whitelisting before deploying | Call third-party APIs directly without whitelisting on the OLB |
| Do | Don't |
|---|---|
Use sdk.getHttpClient() for all API calls | Use raw fetch() or import Axios directly |
Import SDK from @cdx-extensions/di-sdk only | Import from @cdx-extensions/di-sdk-mobile in feature or widget code |
Use React Native StyleSheet for styling | Use web-specific CSS or MUI components |
Use config.ts for API endpoint configuration | Hardcode API URLs directly in component code |
Modify userContext.json to test different user scenarios locally | Change the structure of package.json exports |
Add mock endpoints to apiResponses.json for local testing | Remove existing entries from root package.json |
Keep peerDependencies aligned with those in the README | Change React, React Native, or SDK versions independently |
Export your component from src/index.ts with both named and default exports | Forget the default export — some hosts use import Component from '...' |
Test in the sandbox (playground/mobile-sandbox) before submitting your build output | Assume your code works without running it on a device or simulator |
Set isMock = false in httpClient.js only for local real-call testing | Commit node_modules/ changes |
| Contact the support team for domain whitelisting before deploying | Call third-party APIs directly without whitelisting |